﻿<template>
  <base-container>
    <base-table-card class="mb78px!">
      <el-form ref="formRef" :model="form" :rules="formRules" class="content-form">
        <!-- 同宽容器 -->
        <div class="max-w-[560px] w-full">
          <!-- 服务类目（编辑态禁用） -->
          <el-form-item label="服务类目" prop="categoryPath" class="w-full">
            <el-cascader
              v-model="form.categoryPath"
              :options="catOptions"
              :props="cascaderProps"
              :disabled="loadingCats || isEdit"
              clearable
              collapse-tags
              collapse-tags-tooltip
              placeholder="请选择服务类目"
              class="w-full"
            />
            <template v-if="!loadingCats && catOptions.length === 0 && !isEdit">
              <span class="ml-3 text-[var(--dr)]">
                你还未设置内容类目，无法选择。
                <el-link type="primary" :underline="false" @click="handleGotoCategory"> 去设置类目 &gt; </el-link>
              </span>
            </template>
          </el-form-item>

          <!-- 内容标题（编辑态可改） -->
          <el-form-item label="内容标题" prop="title" class="w-full">
            <el-input
              v-model.trim="form.title"
              maxlength="100"
              show-word-limit
              placeholder="请输入，限制100字"
              clearable
              class="w-full"
            />
          </el-form-item>
        </div>

        <!-- 富文本（编辑态可改） -->
        <el-form-item label="内容详情" prop="contentHtml">
          <div class="relative w-full max-w-[1200px] overflow-hidden rounded-[8px] border border-[var(--cb1)]">
            <div v-if="uploading" class="absolute inset-0 z-10 flex items-center justify-center bg-white/60">
              <el-progress :percentage="progress" type="circle" :width="96" :color="progressColor" />
            </div>

            <Toolbar :editor="editorRef" :default-config="toolbarCfg" mode="default" />
            <Editor
              v-model="form.contentHtml"
              :default-config="editorCfg"
              :style="{ height: editorHeight }"
              mode="default"
              @on-created="handleEditorCreated"
              @on-change="handleEditorChange"
            />
          </div>
        </el-form-item>

        <!-- 发送时间（编辑态禁用） -->
        <el-form-item label="发送时间" prop="sendMode">
          <el-radio-group v-model="form.sendMode" :disabled="isEdit">
            <el-radio :label="'NOW'">立即发送</el-radio>
            <el-radio :label="'MANUAL'">手动发送</el-radio>
            <el-radio :label="'SCHEDULE'">定时发送</el-radio>
          </el-radio-group>
          <el-date-picker
            v-if="form.sendMode === 'SCHEDULE'"
            v-model="form.scheduleTime"
            class="ml-2"
            type="datetime"
            value-format="YYYY-MM-DD HH:mm:ss"
            placeholder="选择发送时间"
            :disabled="isEdit"
            :disabled-date="isDateDisabled"
            @change="handleScheduleChange"
          />
        </el-form-item>

        <!-- 触达对象（来自字典；按类目过滤；编辑态禁用） -->
        <el-form-item label="触达对象" prop="targets">
          <el-checkbox-group v-model="form.targets" :disabled="isEdit">
            <el-checkbox v-for="opt in targetOptions" :key="opt.value" :label="opt.value">
              {{ opt.label }}
            </el-checkbox>
          </el-checkbox-group>
        </el-form-item>

        <!-- 商家筛选（仅当包含"商家"code 才展示；编辑态禁用） -->
        <el-form-item v-if="form.targets.includes(merchantCode)" class="merchant-block">
          <div class="merchant-card">
            <el-form-item label="商家等级" prop="merchantGrade" class="mb-2">
              <el-checkbox-group v-model="form.merchantGrade" :disabled="isEdit">
                <el-checkbox v-for="opt in merchantGradeOptions" :key="opt.value" :label="opt.value">
                  {{ opt.label }}
                </el-checkbox>
              </el-checkbox-group>
            </el-form-item>

            <el-form-item label="商家类型" prop="merchantType">
              <el-checkbox-group v-model="form.merchantType" :disabled="isEdit">
                <el-checkbox v-for="opt in merchantTypeOptions" :key="opt.value" :label="opt.value">
                  {{ opt.label }}
                </el-checkbox>
              </el-checkbox-group>
            </el-form-item>
          </div>
        </el-form-item>
      </el-form>
    </base-table-card>

    <!-- 底部按钮 -->
    <div class="footer">
      <el-button class="w-50" size="large" type="primary" :loading="submitting" @click="handleSubmit">
        {{ isEdit ? "保存修改" : "确认新增" }}
      </el-button>
    </div>
  </base-container>
</template>

<script setup name="AddContent">
  /* ---------------- 路由 / 编辑态 ---------------- */
  import { useRouter, useRoute } from "vue-router";
  import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
  import useWangUpload from "@/utils/useWangUpload";

  const route = useRoute();
  const router = useRouter();
  const id = computed(() => String(route.query.id || route.params.id || ""));
  const isEdit = computed(() => !!id.value);

  /* ---------------- 常量 / 映射 ---------------- */
  const progressColor = ref("var(--bd)");
  const PLATFORM = 1;
  const SEND_MAP = { NOW: "01", MANUAL: "02", SCHEDULE: "03" };
  const SEND_CODE_TO_MODE = { "01": "NOW", "02": "MANUAL", "03": "SCHEDULE" };

  /* ---------------- 表单 / 校验 ---------------- */
  const formRef = ref();
  const submitting = ref(false);
  const form = reactive({
    categoryPath: [], // [l1, l2?, l3?]
    title: "",
    contentHtml: "",
    sendMode: "NOW",
    scheduleTime: "",
    targets: [], // ["01","02","03"] - 字典值
    merchantGrade: [], // 来自字典的值
    merchantType: [], // 来自字典的值
  });
  function hasMeaningfulContent(html) {
    if (!html) return false;
    const div = document.createElement("div");
    div.innerHTML = html;

    // 文字内容
    const text = (div.textContent || "")
      .replace(/[\u00A0\u200B]/g, "") // nbsp/零宽
      .trim();
    if (text.length > 0) return true;

    // 媒体或结构性内容也算有效
    return !!div.querySelector(
      "img,video,audio,iframe,embed,object,canvas,svg,table tr,ul li,ol li,blockquote,pre,code"
    );
  }
  const createRules = {
    categoryPath: [{ required: true, message: "请选择服务类目", trigger: "change" }],
    title: [{ required: true, message: "请输入内容标题", trigger: "blur" }],

    contentHtml: [
      { required: true, message: "请输入内容详情", trigger: ["change", "blur"] },
      {
        validator: (_r, v, cb) => (hasMeaningfulContent(v) ? cb() : cb(new Error("请输入内容详情"))),
        trigger: ["change", "blur"],
      },
    ],
    sendMode: [{ required: true, message: "请选择发送时间", trigger: "change" }],
    targets: [{ required: true, type: "array", message: "请选择触达对象", trigger: "change" }],
    merchantGrade: [
      {
        validator: (_r, v, cb) => {
          // 如果选择了商家但商家等级为空，则校验失败
          if (form.targets.includes(String(merchantCode.value)) && (!v || v.length === 0)) {
            return cb(new Error("请选择商家等级"));
          }
          return cb();
        },
        trigger: ["change"],
      },
    ],
    merchantType: [
      {
        validator: (_r, v, cb) => {
          // 如果选择了商家但商家类型为空，则校验失败
          if (form.targets.includes(String(merchantCode.value)) && (!v || v.length === 0)) {
            return cb(new Error("请选择商家类型"));
          }
          return cb();
        },
        trigger: ["change"],
      },
    ],
  };
  const editRules = {
    title: createRules.title,
    contentHtml: createRules.contentHtml,
  };
  const formRules = computed(() => (isEdit.value ? editRules : createRules));

  /* ---------------- 类目树 ---------------- */
  const loadingCats = ref(true);
  const catOptions = ref([]);
  const cascaderProps = {
    value: "id",
    label: "categoryName",
    children: "children",
    checkStrictly: true,
    emitPath: true,
  };

  const loadCategoryTree = async () => {
    loadingCats.value = true;
    try {
      const res = await Api.service.GetServiceCategoryTree({});
      const payload = res?.data ?? res;
      catOptions.value = Array.isArray(payload) ? payload : [];
    } catch (e) {
      console.error("加载服务类目树失败:", e);
      catOptions.value = [];
    } finally {
      loadingCats.value = false;
    }
  };

  /** 从树里按路径找节点 */
  const findNodeByPath = (options, path) => {
    if (!Array.isArray(path) || path.length === 0) return null;
    let nodes = options || [];
    let cur = null;
    for (const nid of path) {
      cur = (nodes || []).find(n => String(n.id) === String(nid));
      if (!cur) return null;
      nodes = cur.children || [];
    }
    return cur;
  };

  /* ---------------- 触达对象（字典 + 类目过滤） ---------------- */
  const dictAllTargets = ref([]); // [{label,value}]
  const fallbackAllTargets = [
    { label: "客户", value: "01" },
    { label: "商家", value: "02" },
    { label: "租户", value: "03" },
  ];
  const targetOptions = ref([]);

  const merchantCode = computed(() => {
    const hit = (dictAllTargets.value.length ? dictAllTargets.value : fallbackAllTargets).find(o =>
      /商家/.test(String(o.label || ""))
    );
    return hit ? String(hit.value) : "02";
  });

  const loadApplicableDict = async () => {
    try {
      const res = await Api.dict.GetListChildrenByDictCode({
        dictCode: "qingyun.support.serviceCenter.applicableObject",
      });
      const list = Array.isArray(res?.data) ? res.data : Array.isArray(res) ? res : [];
      dictAllTargets.value = list.map(i => ({ label: i.dictLabel, value: String(i.dictValue) }));
    } catch (e) {
      console.error("加载触达对象字典失败：", e);
      dictAllTargets.value = [];
    } finally {
      targetOptions.value = (dictAllTargets.value.length ? dictAllTargets.value : fallbackAllTargets).slice();
    }
  };

  /** 根据选中类目过滤触达对象选项，并校正已选值 */
  const handleRefreshTargetsByCategory = () => {
    const all = dictAllTargets.value.length ? dictAllTargets.value : fallbackAllTargets;

    if (!Array.isArray(form.categoryPath) || form.categoryPath.length === 0) {
      targetOptions.value = all.slice();
      return;
    }

    const node = findNodeByPath(catOptions.value, form.categoryPath);
    let allowCodes = [];
    if (node && node.applicableObjects) {
      allowCodes = String(node.applicableObjects)
        .split(",")
        .map(s => s.trim())
        .filter(Boolean);
    } else {
      targetOptions.value = all.slice();
      return;
    }

    const allowSet = new Set(allowCodes);
    targetOptions.value = all.filter(o => allowSet.has(String(o.value)));
    form.targets = (form.targets || []).filter(c => allowSet.has(String(c)));

    if (!allowSet.has(String(merchantCode.value))) {
      form.merchantGrade = [];
      form.merchantType = [];
    }
  };

  /* ---------------- 商家等级 / 类型（字典） ---------------- */
  const merchantGradeOptions = ref([]); // [{label,value}]
  const merchantTypeOptions = ref([]); // [{label,value}]

  const loadMerchantDicts = async () => {
    try {
      // 商家等级
      const resLevel = await Api.dict.GetListChildrenByDictCode({
        dictCode: "qingyun.support.customer.merchant.level",
      });
      const listLevel = Array.isArray(resLevel?.data) ? resLevel.data : Array.isArray(resLevel) ? resLevel : [];
      merchantGradeOptions.value = listLevel.map(i => ({
        label: i.dictLabel,
        value: String(i.dictValue),
      }));

      // 商家类型
      const resType = await Api.dict.GetListChildrenByDictCode({
        dictCode: "qingyun.support.customer.merchant.type",
      });
      const listType = Array.isArray(resType?.data) ? resType.data : Array.isArray(resType) ? resType : [];
      merchantTypeOptions.value = listType.map(i => ({
        label: i.dictLabel,
        value: String(i.dictValue),
      }));
    } catch (e) {
      console.error("加载商家等级/类型字典失败：", e);
      merchantGradeOptions.value = [];
      merchantTypeOptions.value = [];
    }
  };

  /** 选中"商家"时默认勾选等级/类型；取消时清空 */
  watch(
    () => form.targets.slice().sort().join(","),
    v => {
      const hasMerchant = v.split(",").includes(String(merchantCode.value));
      if (hasMerchant) {
        if (form.merchantGrade.length === 0 && merchantGradeOptions.value.length) {
          form.merchantGrade = merchantGradeOptions.value.map(o => String(o.value));
        }
        if (form.merchantType.length === 0 && merchantTypeOptions.value.length) {
          form.merchantType = merchantTypeOptions.value.map(o => String(o.value));
        }
      } else {
        form.merchantGrade = [];
        form.merchantType = [];
      }

      // 触达对象变化时，清除商家等级和类型的校验错误
      nextTick(() => {
        if (formRef.value) {
          formRef.value.clearValidate(["merchantGrade", "merchantType"]);
        }
      });
    }
  );

  /** 监听类目变更，联动触达对象选项 */
  watch(
    () => form.categoryPath.slice(),
    () => handleRefreshTargetsByCategory()
  );

  /* ---------------- wangEditor ---------------- */
  const editorRef = ref();
  const editorHeight = "360px";
  const toolbarCfg = { excludeKeys: [] };
  const { menuConf, uploading, progress } = useWangUpload({
    imgMaxMB: 10,
    fileMaxMB: 20,
    videoMaxMB: 100,
    isSecretFile: false,
  });
  const editorCfg = { placeholder: "请输入内容…", MENU_CONF: menuConf };
  const handleEditorCreated = editor => (editorRef.value = Object.seal(editor));

  // 处理富文本编辑器内容变化，清除验证错误
  const handleEditorChange = () => {
    // 延迟执行，确保内容已经更新
    nextTick(() => {
      if (formRef.value && hasMeaningfulContent(form.contentHtml)) {
        formRef.value.clearValidate("contentHtml");
      }
    });
  };

  onBeforeUnmount(() => editorRef.value?.destroy?.());

  /* ---------------- 其它 ---------------- */
  const MIN_OFFSET_MIN = 5;
  const MS = 60 * 1000;
  const getMinDT = () => new Date(Date.now() + MIN_OFFSET_MIN * MS);

  /** 禁用日期：只允许今天（含）以后的日期 */
  const isDateDisabled = date => {
    const min = getMinDT();
    const d0 = new Date(date);
    d0.setHours(0, 0, 0, 0);
    const m0 = new Date(min);
    m0.setHours(0, 0, 0, 0);
    return d0.getTime() < m0.getTime();
  };

  /** 简单格式化为 YYYY-MM-DD HH:mm:ss */
  const pad = n => (n < 10 ? "0" + n : "" + n);
  const formatDateTime = dt => {
    const y = dt.getFullYear();
    const m = pad(dt.getMonth() + 1);
    const d = pad(dt.getDate());
    const h = pad(dt.getHours());
    const mi = pad(dt.getMinutes());
    const s = pad(dt.getSeconds());
    return `${y}-${m}-${d} ${h}:${mi}:${s}`;
  };

  /** 变更时强制不早于“当前 + 5 分钟” */
  const handleScheduleChange = val => {
    if (!val) return;
    const picked = new Date(val).getTime();
    const min = getMinDT().getTime();
    if (Number.isFinite(picked) && picked < min) {
      $msg?.warning?.(`请选择 ${MIN_OFFSET_MIN} 分钟之后的时间`);
      form.scheduleTime = formatDateTime(new Date(min));
    }
  };

  const handleGotoCategory = () => router.push({ path: "/service/ServiceList" });

  /* ---------------- 详情回显 ---------------- */
  const resetForm = () => {
    formRef.value?.resetFields?.();
    form.contentHtml = "";
    form.sendMode = "NOW";
    form.scheduleTime = "";
    form.targets = [];
    form.merchantGrade = [];
    form.merchantType = [];
  };
  watch(
    id,
    async newId => {
      if (!newId) {
        resetForm();
        handleRefreshTargetsByCategory();
        return;
      }
      await loadDetail(newId);
    },
    { immediate: true }
  );

  async function loadDetail(detailId) {
    try {
      if (catOptions.value.length === 0) await loadCategoryTree();
      if (!dictAllTargets.value.length) await loadApplicableDict();
      if (!merchantGradeOptions.value.length || !merchantTypeOptions.value.length) await loadMerchantDicts();

      const res = await Api.service.DetailServiceContent({ id: detailId });
      const d = res?.data ?? {};

      // 1) 类目路径
      const path = [d.categoryLevel1Id, d.categoryLevel2Id, d.categoryLevel3Id].filter(Boolean);
      form.categoryPath = path;
      handleRefreshTargetsByCategory();

      // 2) 标题 & 内容
      form.title = d.title || "";
      form.contentHtml = d.content || "";

      // 3) 发送方式 & 时间
      form.sendMode = SEND_CODE_TO_MODE[d.sendMethod] || "NOW";
      form.scheduleTime = d.scheduledSendTime || "";

      // 4) 触达对象（逗号分隔的 codes）
      form.targets = d.applicableObjects
        ? String(d.applicableObjects)
            .split(",")
            .map(s => s.trim())
            .filter(Boolean)
        : [];

      // 5) 商家等级/类型（直接使用 codes）
      form.merchantGrade = d.businessLevel
        ? String(d.businessLevel)
            .split(",")
            .map(s => s.trim())
            .filter(Boolean)
        : [];
      form.merchantType = d.businessType
        ? String(d.businessType)
            .split(",")
            .map(s => s.trim())
            .filter(Boolean)
        : [];
    } catch (e) {
      console.error("获取详情失败", e);
    }
  }

  /* ---------------- 提交 ---------------- */
  const DEFAULT_LIST_ROUTE = { name: "ContentList" }; // 或 { path: '/service/ContentList' }

  function goBackToList() {
    const q = route && route.query ? route.query.returnTo : null; // 可能是 undefined
    if (typeof q === "string" && q) {
      // 用 replace 避免历史栈多一条
      router.replace(q);
    } else if (window.history.length > 1) {
      router.back();
    } else {
      router.replace(DEFAULT_LIST_ROUTE);
    }
  }
  const handleSubmit = async () => {
    if (isEdit.value) {
      const payload = {
        id: Number(id.value),
        title: form.title,
        content: form.contentHtml,
      };
      try {
        submitting.value = true;
        await Api.service.UpdateServiceContent(payload);
        $msg.success("保存成功");
        goBackToList();
      } finally {
        submitting.value = false;
      }
      return;
    }

    if (form.sendMode === "SCHEDULE") {
      if (!form.scheduleTime) return $msg.warning("请选择定时发送时间");
      if (new Date(form.scheduleTime).getTime() <= Date.now()) return $msg.warning("发送时间需大于当前时间");
    }

    const ok = await formRef.value
      .validate()
      .then(() => true)
      .catch(() => false);
    if (!ok) return;

    const [level1, level2, level3] = form.categoryPath;

    const addPayload = {
      categoryLevel1Id: level1 ?? "",
      categoryLevel2Id: level2 ?? "",
      categoryLevel3Id: level3 ?? "",
      title: form.title,
      content: form.contentHtml,
      sendMethod: SEND_MAP[form.sendMode],
      scheduledSendTime: form.sendMode === "SCHEDULE" ? form.scheduleTime : "",
      platform: PLATFORM,
      applicableObjects: (form.targets || []).join(","),

      // 直接提交字典 value（后端需要 codes）
      businessLevel: form.targets.includes(String(merchantCode.value)) ? (form.merchantGrade || []).join(",") : "",
      businessType: form.targets.includes(String(merchantCode.value)) ? (form.merchantType || []).join(",") : "",
    };

    try {
      submitting.value = true;
      await Api.service.AddServiceContent(addPayload);
      $msg.success("新增成功");
      resetForm();
      goBackToList();
    } finally {
      submitting.value = false;
    }
  };

  /* ---------------- 生命周期监听 ---------------- */
  onMounted(() => {
    console.log("AddContent onMounted - 组件挂载");
  });

  onActivated(() => {
    console.log("AddContent onActivated - 组件被激活（从缓存中恢复）");
    // 每次激活时重新加载数据字典
    Promise.all([loadApplicableDict(), loadCategoryTree(), loadMerchantDicts()]).then(() => {
      handleRefreshTargetsByCategory();
    });
  });
</script>

<style scoped lang="scss">
  /* footer */
  .footer {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;

    display: flex;
    align-items: center;
    justify-content: center;

    width: 100%;
    height: 78px;

    background-color: var(--bg);
  }

  /* 表单容器内边距 */
  .content-form {
    padding: 12px 4px;
  }

  /* 商家筛选卡片 */
  .merchant-card {
    box-sizing: border-box;
    margin-left: 75px;
    padding: 16px;

    border: 1px solid var(--el-border-color);
    border-radius: 8px;

    background: #fff;
  }

  /* 间距工具类 */
  .mb-2 {
    margin-bottom: 8px;
  }

  /* 标签右对齐 */
  :deep(.el-form-item--label-right .el-form-item__label) {
    justify-content: center;
  }
</style>
